package edu.zut.main.thread;

public class ThreadCommunication {
    public static void main(String[] args) {
        Stack stack = new Stack();
        //生产线程
        new Thread(() -> {
            while (true){
                char c = (char) (Math.random()*26 + 'A');
                stack.push(c);
            }
        }).start();
        //消费线程
        new Thread(() -> {
            while (true){
                char c = stack.pop();
//                System.out.println("消费了：" + c);
            }
        }).start();
    }

}
/**
 * 线程通信：
 *  生产者与消费者
 *  生产者：生产产品，当消费者需要时；如果库存满了，就不需要生产了，此时我们就处于等待。
 *      一旦消费者消费完，生产者补充上新产品后，告诉消费者来消费
 *  消费者：消费产品，必须有产品，如果没有产品，需要唤醒生产者生产产品
 */
//模拟往堆栈中保存数据
class Stack{
    //模拟下标的变化记录
    private int point = 0;
    //容器，保存数据
    private char[] data = new char[5];

    //将数据放入data
    public synchronized void push(char ch){
        //如果point等于data的长度，说明data中保存的数据已经满了
        while (point == data.length){
            //数据保存满了，需要生产数据的操作转为等待，告诉消费者pop赶紧取出数据
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //唤醒消费者pop消费数据
        this.notifyAll();
        data[point] = ch;
        System.out.println("生产了" + ch);
        point ++;
    }


    //从data中取出数据
    public synchronized char pop(){
        //如果point为0，说明data中已无数据，让当前pop等待，让push唤醒开始生产
        while (point == 0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        this.notifyAll();
        point--;
        System.out.println("消费了：" + data[point]);
        return data[point];
    }



}